/**
 * User: alesj
 * Date: 2004.8.30
 * Time: 10:57:33
 */

package com.generalynx.common.utils;

import java.util.Calendar;
import java.util.Date;
import java.text.DateFormat;

public class DateData implements Comparable, Cloneable, IDate {
    protected boolean m_bValid;
    protected int m_nYear;
    protected int m_nMonth;
    protected int m_nDay;

    public DateData() {
        this(true);
    }

    public DateData(boolean bValid) {
        if (bValid) {
            setValue(Calendar.getInstance());
        } else {
            m_bValid = false;
        }
    }

    public DateData(Calendar calendar) {
        setValue(calendar);
    }

    public DateData(long timeStamp) {
        setValue(new Date(timeStamp));
    }

    public DateData(Date date) {
        setValue(date);
    }

    public DateData(DateData date) {
        setValue(date);
    }

    public int hashCode() {
        return getDate().hashCode();
    }

    public boolean isValid() {
        return m_bValid;
    }

    public int getYear() {
        return m_nYear;
    }

    public void setYear(int nYear) {
        m_nYear = nYear;
    }

    public int getMonth() {
        return m_nMonth;
    }

    public void setMonth(int nMonth) {
        m_nMonth = nMonth;
    }

    public int getDay() {
        return m_nDay;
    }

    public void setDay(int nDay) {
        m_nDay = nDay;
    }

    public void setValue(Calendar calendar) {
        if (calendar == null) {
            m_bValid = false;
        } else {
            setValue(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH) - Calendar.JANUARY + 1, calendar.get(Calendar.DAY_OF_MONTH));
        }
    }

    public void setValue(Date date) {
        if (date == null) {
            m_bValid = false;
        } else {
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(date);
            setValue(calendar);
        }
    }

    public void setValue(DateData date) {
        if (date == null) {
            m_bValid = false;
        } else {
            setValue(date.m_bValid, date.m_nYear, date.m_nMonth, date.m_nDay);
        }
    }

    public void setValue(int nYear, int nMonth, int nDay) {
        setValue(true, nYear, nMonth, nDay);
    }

    public void setValue(boolean bValid, int nYear, int nMonth, int nDay) {
        m_bValid = bValid;
        m_nYear = nYear;
        m_nMonth = nMonth;
        m_nDay = nDay;
    }

    public DateData createNew() {
        DateData newDate = null;
        try {
            newDate = (DateData) clone();
        } catch (CloneNotSupportedException ex) {
        }

        return newDate;
    }

    public DateData createNew(int nDays) {
        DateData newDate = createNew();
        return newDate.addDays(nDays);
    }

    public DateData addDays(int nDays) {
        if (nDays != 0) {
            Calendar calendar = toCalendar();
            calendar.add(Calendar.DATE, nDays);
            setValue(calendar);
        }
        return this;
    }

    public boolean isBefore(DateData value) {
        return (m_bValid && (value == null || !value.isValid() || (toLong() < value.toLong())));
    }

    public boolean isAfter(DateData value) {
        return !isBeforeOrEqual(value);
    }

    public boolean isBeforeOrEqual(DateData value) {
        return (isBefore(value) || isEqual(value));
    }

    public boolean isAfterOrEqual(DateData value) {
        return !isBefore(value);
    }

    public boolean isEqual(DateData value) {
        return
                (!m_bValid && (value == null || !value.isValid())) ||
                (m_bValid && value.isValid() && (toLong() == value.toLong()));
    }

    public boolean isBetween(DateData fromValue, DateData toValue) {
        return (isAfterOrEqual(fromValue) && isBeforeOrEqual(toValue));
    }

    public long toLong() {
        return ((m_nYear * 12 + m_nMonth) * 31 + m_nDay) * 24 * 60 * 60;
    }

    public Calendar toCalendar() {
        Calendar calendar = Calendar.getInstance();
        calendar.set(m_nYear, m_nMonth - 1 + Calendar.JANUARY, m_nDay);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar;
    }

    public Date getDate() {
        return toTruncatedCalendar().getTime();
    }

    public Calendar toTruncatedCalendar() {
        Calendar calendar = Calendar.getInstance();
        calendar.set(m_nYear, m_nMonth - 1 + Calendar.JANUARY, m_nDay, 0, 0, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar;
    }

    public boolean equals(Object obj) {
        DateData date = (DateData) obj;
        return isEqual(date);
    }

    public String format(DateFormat df) {
        return df.format(getDate());
    }

    public String toString() {
        return new StringBuffer()
                .append(m_nYear)
                .append("-")
                .append(m_nMonth)
                .append("-")
                .append(m_nDay).toString();
    }

    public int compareTo(Object o) {
        DateData d = (DateData) o;
        return isBefore(d) ? -1 : (isAfter(d) ? 1 : 0);
    }
}
